/**
 * Copyright (c) 2015-2030 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.support.wx.request;

import java.util.SortedMap;
import java.util.TreeMap;

import com.alibaba.fastjson.JSONObject;
import com.yanlight.util.LogUtil;
import org.apache.commons.lang3.StringUtils;

import com.yanlight.support.http.AbstractRequest;
import com.yanlight.support.http.RequestBuilder;
import com.yanlight.support.wx.WxConstants;
import com.yanlight.support.wx.response.WxOrderResponse;

/**
 * @author haolw
 * @time 2017/07/20
 */
public class WxOrderRequest extends AbstractRequest<WxOrderResponse> {
    // 必填
    private String appId;// 微信分配的公众账号ID
    private String mchId;// 微信支付分配的商户号
    // 服务商模式下必填
    private String subMchId;// 微信支付分配的子商户号
    // 必填
    private String body;// 商品简单描述，该字段须严格按照规范传递
    private String outTradeNo;// 商户系统内部的订单号,32个字符内、可包含字母
    private Integer totalFee;// 订单总金额，单位为分
    private String spbillCreateIp;// APP和网页支付提交用户端ip，Native支付填调用微信支付API的机器IP
    private String notifyUrl;// 接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数
    private String tradeType = "JSAPI";// 取值如下：JSAPI，NATIVE，APP

    // 非必填
    private String deviceInfo;// 终端设备号(门店号或收银设备ID)，注意：PC网页或公众号内支付请传"WEB"
    private String detail;// 商品详细列表，使用Json格式，传输签名前请务必使用CDATA标签将JSON文本串保护起来
    private String attach;// 附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
    private String feeType = "CNY";// 符合ISO 4217标准的三位字母代码，默认人民币：CNY
    private String timeStart;// 订单生成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010
    private String timeExpire;// 订单失效时间，格式为yyyyMMddHHmmss，如2009年12月27日9点10分10秒表示为20091227091010,注意：最短失效时间间隔必须大于5分钟
    private String goodsTag;// 商品标记，代金券或立减优惠功能的参数
    private String productId;// trade_type=NATIVE，此参数必传。此id为二维码中包含的商品ID，商户自行定义
    private String limitPay;// no_credit--指定不能使用信用卡支付
    private String openid;// trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识

    // 服务商模式下非必填
    private String subAppId;// 微信分配的子商户公众账号ID，如需在支付完成后获取sub_openid则此参数必传
    private String subOpenid;// trade_type=JSAPI，此参数必传，用户在子商户appid下的唯一标识。openid和sub_openid可以选传其中之一，如果选择传sub_openid,则必须传sub_appid
    private SortedMap<String, String> paramsMap;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getMchId() {
        return mchId;
    }

    public void setMchId(String mchId) {
        this.mchId = mchId;
    }

    public String getSubMchId() {
        return subMchId;
    }

    public void setSubMchId(String subMchId) {
        this.subMchId = subMchId;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public void setOutTradeNo(String outTradeNo) {
        this.outTradeNo = outTradeNo;
    }

    public Integer getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(Integer totalFee) {
        this.totalFee = totalFee;
    }

    public String getSpbillCreateIp() {
        return spbillCreateIp;
    }

    public void setSpbillCreateIp(String spbillCreateIp) {
        this.spbillCreateIp = spbillCreateIp;
    }

    public String getNotifyUrl() {
        return notifyUrl;
    }

    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }

    public String getTradeType() {
        return tradeType;
    }

    public void setTradeType(String tradeType) {
        this.tradeType = tradeType;
    }

    public String getDeviceInfo() {
        return deviceInfo;
    }

    public void setDeviceInfo(String deviceInfo) {
        this.deviceInfo = deviceInfo;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getAttach() {
        return attach;
    }

    public void setAttach(String attach) {
        this.attach = attach;
    }

    public String getFeeType() {
        return feeType;
    }

    public void setFeeType(String feeType) {
        this.feeType = feeType;
    }

    public String getTimeStart() {
        return timeStart;
    }

    public void setTimeStart(String timeStart) {
        this.timeStart = timeStart;
    }

    public String getTimeExpire() {
        return timeExpire;
    }

    public void setTimeExpire(String timeExpire) {
        this.timeExpire = timeExpire;
    }

    public String getGoodsTag() {
        return goodsTag;
    }

    public void setGoodsTag(String goodsTag) {
        this.goodsTag = goodsTag;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getLimitPay() {
        return limitPay;
    }

    public void setLimitPay(String limitPay) {
        this.limitPay = limitPay;
    }

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }

    public String getSubAppId() {
        return subAppId;
    }

    public void setSubAppId(String subAppId) {
        this.subAppId = subAppId;
    }

    public String getSubOpenid() {
        return subOpenid;
    }

    public void setSubOpenid(String subOpenid) {
        this.subOpenid = subOpenid;
    }

    public SortedMap<String, String> getParamsMap() {
        if (paramsMap == null) {
            paramsMap = new TreeMap<String, String>();
        }

        LogUtil.showLog(JSONObject.toJSONString(paramsMap));

        paramsMap.put("appid", appId);
        paramsMap.put("mch_id", mchId);
        paramsMap.put("body", body);
        paramsMap.put("out_trade_no", outTradeNo);
        paramsMap.put("total_fee", totalFee.toString());
        paramsMap.put("spbill_create_ip", spbillCreateIp);
        paramsMap.put("notify_url", notifyUrl);
        paramsMap.put("trade_type", tradeType);
        paramsMap.put("fee_type", feeType);

        if (StringUtils.isNotBlank(deviceInfo)) {
            paramsMap.put("device_info", deviceInfo);
        }
        if (StringUtils.isNotBlank(detail)) {
            paramsMap.put("detail", detail);
        }
        if (StringUtils.isNotBlank(attach)) {
            paramsMap.put("attach", attach);
        }
        if (StringUtils.isNotBlank(attach)) {
            paramsMap.put("time_start", timeStart);
        }
        if (StringUtils.isNotBlank(attach)) {
            paramsMap.put("time_expire", timeExpire);
        }
        if (StringUtils.isNotBlank(attach)) {
            paramsMap.put("goods_tag", goodsTag);
        }
        if (StringUtils.isNotBlank(productId)) {
            paramsMap.put("product_id", productId);
        }
        if (StringUtils.isNotBlank(openid)) {
            paramsMap.put("openid", openid);
        }
        if (StringUtils.isNotBlank(limitPay)) {
            paramsMap.put("limit_pay", limitPay);
        }

        if (StringUtils.isNotBlank(subMchId)) {
            paramsMap.put("sub_mch_id", subMchId);
        }
        if (StringUtils.isNotBlank(subAppId)) {
            paramsMap.put("sub_appid", subAppId);
        }
        if (StringUtils.isNotBlank(subOpenid)) {
            paramsMap.put("sub_openid", subOpenid);
        }
        return paramsMap;
    }

    @Override
    protected void execute(RequestBuilder builder) {
        builder.addParams(paramsMap);
        builder.post().contentXML().dataXML().setUrl(WxConstants.WX_UNIFIEDORDER_URL);
    }
}
